<?php
	
	if (file_exists('bmconfig.php'))
		require_once 'bmconfig.php';  

	require_once 'file.php';
	require_once 'dir.php';
    
    function boolToStr($b)
    {
        return $b ? 'true' : 'false';
    }
	
    /**
     * Returns the last position of $delim in $string
     */
	function lastDelimiter($delim, $string)
	{
		$i = strlen($string);
		$i--;
		
		while ($i >= 0)
		{
			if ($string[$i] == $delim)
				return $i;
                
			$i--;
		}
	}
	
	/**
	 * In case magic_quotes_gpc() is enabled
	 * removes the slashes from the string parameter
	 * 
	 * @param string $string
	 * @return string
	 */
	function gpcSlashes($string)
	{
		return get_magic_quotes_gpc() ? stripslashes($string) : $string;
	}
	
	function getMime($ft)
	{
		switch(strtolower($ft))
		{
			case "php"  :
			case "py"   :
			case "asp"  :
			case "aspx" : 
			case "xml"  :
			case "txt"  : 
			case "js"   :
            case "pas"  :
            case "inc"  :
            case "c"    :
            case "cpp"  :
            case "cs"   :
            case "java" :
			case "css"  : return "text/plain";
			
			default     : return "application/octet-stream";
		}
	}        
	
	/**
	* Returns true if the filename passed on the argument
	* contains no illegal characters
	* 
	* The argument must be only a file NAME not a path
	*/
	function isValidFilename($s)
	{
		$disallowed = array("\\", "/", ":", "*", "?", '"', "<", ">", "|" );
		
		$f = new File($s);
		$s = $f->getFilename();
		
		foreach($disallowed as $item)
			if (strpos($s, $item) !== false) 
				return false;
		
		return true;
	}
	
	function hasAccess($dir)
	{
		return is_readable($dir);
	}
	
	/**
	 * Takes an int and returns a string
	 * representing it's file size
	 * 
	 * @param int $fs the number (in bytes) which will
	 * be converted
	 * @return the string representation of the integer
	 * @example intToFileSize(700) will return '700 b'
	 */
	function intToFileSize($fs)
	{
		$metrics = array('b', 'kb', 'mb', 'gb', 'tb');
		$i = 0;
		
		while ($fs > 1024)
		{
			$fs /= 1024;
			$i++;
			
			// Check if $i is going out of bounds
			if ($i + 1 == count($metrics))
				break;
		}
		
		# Round with 2 decimal digits
		$fs = round($fs, 2);
		
		return "$fs {$metrics[$i]}";
	}
	
	/**
	 * If the last character of the string is '/' it removes it
	 * from the string
	 * 
	 * @param string $s the string to be checked
	 * @return string the string without trailing blackslash
	 */
	function exludeTrailingBackslash($s)
	{
		if (strlen($s) == 0)
			return;
		
		// If the last character is a backslash
		// remove it.
		if ($s[strlen($s) -1] == '/')
			return substr($s, 0, strlen($s) - 1);
			
		// else return the original string
		return $s;    
	}
	
	/**
	 * Makes sure that the last character of the string
	 * $s is a backslash. If it isn't, it is added by this function
	 *
	 * @param string $s the string to check for the backslash
	 * @return string the string with the last character being a backslash
	 *
	 */
	function includeTrailingBackslash($s)
	{
		if (strlen($s) == 0)
			return '/';
	
		// if the last character is not a backslash
		// add one
		if ($s[strlen($s) -1] != '/')
			return $s . '/';
		  
		// else return the original string
		return $s;
	}
	
	/**
	 * Returns the relative path between
	 * directory $root, and $directory $p
	 *
	 * The returned value is the path which must
	 * be traversed from $root in order to go to $p
	 *
	 * @param string $root the 'root' directory
	 * @param string $p the directory which the relative path is needed
	 * @return string the relative path of $p with $root
	 *
	 */
	function dirsGetRelativePath($root, $p)
	{
		$root = explode('/', exludeTrailingBackslash($root));
		$p = explode('/', exludeTrailingBackslash($p));

		$i = 0;
		
		// max holds the number of
		// elements the shortest path has
		$max = min(count($root), count($p));
		
		// Let's skip mutual elements
		while ($root[$i] == $p[$i])
		{
			$i++;
			
			// If we are going out of bounds
			// break the loop
			if ($i >= $max)
				break;
		}
		
		// In case they are the same directory
		if (($i == $max) && (count($root) == count($p)))
			return './';    
	
		// In case p is a subdirectory of root
		// which means that the count stopped right at the 
		// end of the array
		//
		// example : 
		//
		//      c:/www/htdocs/bm
		//      c:/www/htdocs/test/more/tests
		//
		//
		// the counter should have stopped at 2, which should have returned c:/www/htdocs
		// which is the common path
		//
		// then on the second directory the mutual part is removed
		// leaving it with 'test/more/tests'
		// and a ../ is added at the beginning to symbolize the
		// traversal from c:/www/htdocs/bm to c:/www/htdocs
		if (($i + 1 == count($root)))    
			return '../' . implode('/',  array_slice($p, $i));
			
		// root is a subdirectory of p
		$v = './' . implode('/', array_slice($p, count($root)));
		
		return ($v == "") ? "." : $v;    
	}
	
	/**
	 * Gets the relative path of $p to the location of index.php's directory
	 * 
	 * @param string $p the path which we will get it's relative location
	 * @return string the relative path of $p to the document root
	 */
	function getRelativePath($p)
	{
		// All occurrences of '\' should be escaped.
		// The path is returned in a format C:\www\htdocs\etc
		// on windows servers, but the backslash is needed
		// since it is the standard path delimiter on
		// other operating systems
		
		$root = str_replace('\\', '/', realpath('.'));
		$p = str_replace('\\', '/', realpath($p)); 
		
		return dirsGetRelativePath($root, $p); 
	}
	
	/**
	 * Checks wether or not bitmanager should display
	 * the folder provided on the parameter
	 * 
	 * @param mixed $folder - The folder to check
	 * @return bool - True in case the folder is allowed to be viewed
	 */
	function isAllowedView($folder)
	{
		return !in_array(includeTrailingBackslash(getRelativePath($folder)), $GLOBALS["restrictedFolders"]);
	}
	
	function isFileViewAllowed($file)
	{
		$f = new File($file);
		
		return isAllowedView($f->getPath());
	}

	/**
	 * Creates an <img> tag which will display an
	 * image for the file type of the parameter
	 * 
	 * @param string $fn the filename
	 * @return string html code which will contain an img tag
	 * with the apropriate image depending on $fn's extesion
	 */
	function imgFromFile($fn)
	{
		$f = new File($fn);
		
		$ext = $f->getExt();
		$fn = "";
		
		
		switch (strtolower($ext))
		{
			case "ppt" :
			case "pptx" : $fn = "ppt.png"; break;
			
			case "doc" :
			case "docx" : $fn = "doc.png"; break;
			
			case "exe":
			case "dmg":
			case "dll":
			case "oxc":
			case "so":  $fn = "exe.png"; break;
			
			case "xls" :
			case "xlsx" : $fn = "xls.png"; break; 
			
			case "pdf":
			case "xps" : $fn = "pdf.png"; break;
			
			case "c":
			case "h":
			case "cpp":
			case "hpp" : $fn = "c.png"; break;
			
			case "htm":
			case "html": $fn = "html.png"; break;
			
			case "zip":
			case "rar":
			case "7z":
			case "tar":
			case "bzip": $fn = "zip.png"; break;
			
			case "php" : $fn = "php.png"; break;
			
			case "fdb":
			case "db" :
			case "mdb":
			case "accdb": $fn = "db.png"; break;
			
			case "java" : $fn = "java.png"; break;
			
			case "mp3":
			case "wma": $fn = "mp3.png"; break;
			
			case "js" : $fn = "js.png"; break;
			
			case "avi":
			case "flv":
			case "mpg":
			case "swf":
			case "mpeg": $fn = "avi.png"; break;
			
			case "ico":
			case "jpg":
			case "jpeg":
			case "png":
			case "tga":
			case "gif":
			case "bmp": $fn = "img.png"; break;
			
			case "css" : $fn = "css.png"; break;
			
			case "txt" : $fn = "txt.png"; break;
			
			default: $fn = "page.png";
		}
		
		return "<img src='./img/filetypes/{$fn}' height='16' width='16' alt='File image'>";
	}

	/**
	 * Creates the site's top layout and leaves it at the point where
	 * each page must add it's own content.
	 * 
	 * @param string $title page's title
	 * @param mixed $subtitle [optional] any subtitle the webpage might have
	 */
	function initSite($title, $subtitle = "", $noCache = false)
	{
		?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
	<head>
		<title>Bitmanager :: <?php echo $title ?></title>
		<link type="text/css" href="styles/<?php echo defined('ACTIVE_THEME') ? ACTIVE_THEME : 'light' ?>/styles.css" media="all" rel="stylesheet">  
		<link rel="shortcut icon" href="img/orbit.png" type="image/png">
	</head>
<body>
<div id="msgbar"></div>
<!-- .top-menu start -->
<div class="top-menu">
		<span class='title'>Bitmanager :: <?php echo $title ?></span>        
		<span class="subtitle"><?php echo $subtitle ?></span>
</div>
<script type="text/javascript" src="scripts/jquery.js"></script>      
<script type="text/javascript" src="scripts/ajaxapi.js"></script>
<script type="text/javascript" src="scripts/explorer.js"></script>    
<script type="text/javascript">    
$(document).ready
(
	function()
	{  
		$("#bm_menu li").hover(
			function(){
                $("ul", this)
                    .fadeIn(100); 
            }, 
			function(){
                $("ul", this).fadeOut(100); 
            } 
		); 
		
		$("#bm_menu > li > ul").hide();  
	}
);
</script>  
	<?php
	}
	
	/**
	 * Closes the html tags opened by initSite
	 * and displays some additional information
	 * 
	 */
	function finishSite($showInfo = true)
	{
		if ($showInfo)
			getFooter();
		?>
			</body>
			</html>
		<?php
	}
	
	function showFatalError($title, $msg)
	{
		?>  
		<br><br><br><br><br><br>
		<center>
		<div class="forbidden">
            <div class="title"><?php echo isset($title) ? $title : 'Error' ?> <img src="img/exclamation.png"></div>  
			<h3><?php echo $msg ?></h3>
			<br>
			<br>
			<a href="javascript:history.back()">Go back</a>
		</div>
		</center>
		<?php    
	}
    
    function quitWithError($title, $msg)
    {
        initSite('Error!');  
        showFatalError($title, $msg);
        finishSite();
    }
    
    /**
     * Shows an information page
     * 
     * @param string $title the title of the page
     * @param string $msg the displayed message
     * @param array $links a 2d array containing the href and text for the links. In the form $links[0]['href'] = ''; $linls[0]['text'] = ''
     */
    function showInformation($title, $msg, $links)
    {
        ?>  
        <br><br><br><br><br><br>
        <center>
        <div class="infodiv">
            <div class="title"><?php echo $title ?> <img src="img/info.png"></div>
            <h3><?php echo $msg ?></h3>
            <?php foreach($links as $link): ?>
                <a class='hrefbtn'  href="<?php echo $link['href'] ?>"><?php echo $link['text'] ?></a>
            <?php endforeach; ?>
            <br><br>
        </div>
        </center>
        <?php    
    }
    
    function quitWithInfo($title, $msg, $links)
    {
        initSite('');
        showInformation($title, $msg, $links);
        finishSite();
    }
	
	/**
	 * Creates HTML for displaying the top level menu
	 * the html is not printed, but returned
	 * 
	 * @param array $items an array in ('caption' => 'url') style
	 * @return string the html to be displayed
	 * @throws exception in case the supplied argument is not an array
	 * 
	 * @example makeMenu( array(array('home' => 'index.php'), array('edit' => 'editfile.php')) );
	 */
	function makeMenu($items)
	{
		if (!is_array($items))
			throw new Exception("Supplied argument is not an array");
		
		$html = "<div class='top-menu'><ul id='bm_menu'>";
		
		for($i = 0; $i < count($items); $i++)
		{
			$xtra = ($i + 1 != count($items)) ? " // " : "";
			
			$html .= "<li><a href='{$items[$i][1]}'>{$items[$i][0]}</a></li>\n";      
		}
		
		$html .= "\n</ul></div>";
		
		return $html;
	}
					
	/**
	 * Checks wether a user is logged in or not
	 * 
	 * @return bool true/false depending on logon state
	 */
	function isLoggedIn()
	{
		return isset($_SESSION[BM_AUTH]) && $_SESSION[BM_AUTH];
	}
	
	/**
	 * Returns the footer
	 * 
	 */
	function getFooter()
	{
		?>
		
		<div id="foot">
			BitManager 1.0 beta - web based file manager 
			<br>
			<a href="http://code.google.com/p/bitmanager/" target="_blank">[ bitmanager website ]</a>
			
			<a href="http://code.google.com/p/bitmanager/downloads/list" target="_blank">[ download ]</a>

			<a href="http://code.google.com/p/bitmanager/issues/list" target="_blank">[ submit a bug ]</a>
			<br><br>
		</div>
		
		<?php
	}
?>
